using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using OpenComposite.EII.Repository;
using OpenComposite.Repository.Properties;
using System.Xml.Schema;
using System.IO;
using System.Xml;
using System.Diagnostics;
using OpenComposite.EII.Services;
using System.Globalization;

namespace OpenComposite.EII.RepositoryUIs
{
	public partial class UCVerb : RepositoryItemUI
	{
		#region Initialization

		public UCVerb(IServiceProvider serviceProvider)
			: base(serviceProvider)
		{
			InitializeComponent();

			init();
		}
		private void init()
		{
		}

		#endregion

		#region Public Members

		#region Properties
		public override IRepositoryItem RepositoryItem
		{
			get
			{
				save();
				return _verb;
			}
			set
			{
				base.RepositoryItem = value;
				if ( value is Verb ) {
					_verb = (Verb)value;
					load();
				}
			}
		}

		public override string TypeText
		{
			get { return Resources.sVerb; }
		}

		public override string TypeDescription
		{
			get { return ""; }
		}
		#endregion

		#region Events
		#endregion

		#region Methods
		#endregion

		#endregion

		#region Private Members

		#region Variables
		private Verb _verb = null;
		#endregion

		#region Methods
		private void load()
		{
			if ( _verb == null )
				return;

			txtVerbName.Text = _verb.Name;
			txtVerbDesc.Text = _verb.Description;
			showInputOutput();
			displayLogMethod();

			fillKPIList();
			if ( tabCtrlMain.SelectedTab == tabUsedBy ) {
				usedByHierarchyVerb.RepositoryItem = this.RepositoryItem as RepositoryItemBaseEx;
			} else if ( tabCtrlMain.SelectedTab == tabUses ) {
				usingHierarchyVerb.RepositoryItem = this.RepositoryItem as RepositoryItemBaseEx;
			}

		}
		private void save()
		{
			if ( _verb == null )
				_verb = new Verb();

			int inid = _verb.InputBusinessObjectID;
			int outid = _verb.OutputBusinessObjectID;
			int lwmid = _verb.DefaultLogicalMethodID;

			_verb.Reload();

			_verb.Name = txtVerbName.Text;
			_verb.Description = txtVerbDesc.Text;
			_verb.InputBusinessObjectID = inid;
			_verb.OutputBusinessObjectID = outid;

			if ( _verb.DefaultLogicalMethodID > 0 ) {
				_verb.DefaultLogicalMethodID = lwmid;
			} else if ( lwmid > 0 ) {
				Global.Data.SetDefaultLogWMethAtLogicalActivitiesOfCapability(_verb.ID, lwmid);
				_verb.DefaultLogicalMethodID = lwmid;
			}
		}
		private void fillKPIList()
		{
			dgvKPI.AutoGenerateColumns = false;
			dgvKPI.DataSource = Global.Data.GetRepositoryHierarchyChildRepositoryList<KPIMetric>(
									ItemType.Verb, _verb.ID, ItemType.KPI_Metric);
		}

		private void showInputOutput()
		{
			this.SuspendLayout();
			txtInput.SuspendLayout();
			txtOutput.SuspendLayout();
			if ( _verb.InputBusinessObject == null ) {
				txtInput.ForeColor = SystemColors.GrayText;
				txtInput.TextAlign = HorizontalAlignment.Center;
				txtInput.Text = "Please select an input.";
				btnRemoveInput.Enabled = false;
				btnViewInput.Enabled = false;
			} else {
				txtInput.ForeColor = SystemColors.ControlText;
				txtInput.TextAlign = HorizontalAlignment.Left;
				txtInput.Text = _verb.InputBusinessObjectName;
				btnRemoveInput.Enabled = true;
				btnViewInput.Enabled = true;
			}
			if ( _verb.OutputBusinessObject == null ) {
				txtOutput.ForeColor = SystemColors.GrayText;
				txtOutput.TextAlign = HorizontalAlignment.Center;
				txtOutput.Text = "Please select an output.";
				btnRemoveOutput.Enabled = false;
				btnViewOutput.Enabled = false;
			} else {
				txtOutput.ForeColor = SystemColors.ControlText;
				txtOutput.TextAlign = HorizontalAlignment.Left;
				txtOutput.Text = _verb.OutputBusinessObjectName;
				btnRemoveOutput.Enabled = true;
				btnViewOutput.Enabled = true;
			}
			txtInput.ResumeLayout(true);
			txtOutput.ResumeLayout(true);
			this.ResumeLayout(true);
		}
		private void newKPI()
		{
			RepositoryService repSvc = (RepositoryService)_verb.GetService(typeof(RepositoryService));
			if ( repSvc == null )
				throw new NullReferenceException("RepositoryService not available.");

			KPIMetric metric = repSvc.GetItem(ItemType.KPI_Metric, true, Global.Status.CurrentRepositoryId) as Repository.KPIMetric;
			if ( metric != null )
				Global.Data.AddRepositoryHierarchy(_verb, metric, Global.Status.CurrentRepositoryId);

			fillKPIList();
		}
		private void editKPI()
		{
			if ( dgvKPI.SelectedRows.Count > 0 ) {
				KPIMetric metric = dgvKPI.SelectedRows[0].DataBoundItem as KPIMetric;
				Helpers.ShowDetails(metric, serviceProvider);
				//if ( metric != null ) {
				//    KPI.FormKPIMetric frm = new OpenComposite.EII.KPI.FormKPIMetric(metric);
				//    frm.ShowDialog();
				//}
				//fillKPIList();
			}
		}
		private void removeKPI()
		{
			if ( dgvKPI.SelectedRows.Count > 0 ) {
				KPIMetric metric = dgvKPI.SelectedRows[0].DataBoundItem as KPIMetric;
				if ( metric != null )
					metric.Delete(true);
				fillKPIList();
			}
		}

		private void showSchema(BusinessObject bo)
		{
			if ( bo == null || bo.Schema == null )
				return;

			XmlDocument xd = new XmlDocument();
			using ( StringWriter sw = new StringWriter() ) {
				bo.Schema.Write(sw);
				xd.LoadXml(sw.ToString());
			}
			formXmlViewer XmlViewer = new formXmlViewer();
			XmlViewer.XmlDocument = xd;
			XmlViewer.Text = "XML-Schema of Business Object \"" + bo.Name + "\"";
			XmlViewer.ShowDialog();
		}

		private void displayLogMethod()
		{
			if ( _verb.DefaultLogicalMethod == null ) {
				txtLogMethod.Text = "";
				btnRemoveLogMethod.Enabled = false;
			} else {
				txtLogMethod.Text = _verb.DefaultLogicalMethod.Name;
				btnRemoveLogMethod.Enabled = true;
			}
		}

		private void setDefaultLogMethod(LogicalWebMethod defaultLogMethod)
		{
			if ( _verb.DefaultLogicalMethod != null && _verb.DefaultLogicalMethod != defaultLogMethod ) {
				Forms.FormChangeDefaultLogMethod frm =
					new OpenComposite.EII.Forms.FormChangeDefaultLogMethod(_verb, _verb.DefaultLogicalMethod, defaultLogMethod);
				frm.ShowDialog();
			}

			_verb.DefaultLogicalMethod = defaultLogMethod;
		}

		#endregion

		#region Event Handlers

		private void btnNewKPI_Click(object sender, EventArgs e)
		{
			newKPI();
		}
		private void btnRemoveKPI_Click(object sender, EventArgs e)
		{
			removeKPI();
		}
		private void btnEditKPI_Click(object sender, EventArgs e)
		{
			editKPI();
		}

		private void contextKPI_Opening(object sender, CancelEventArgs e)
		{
			Point pt = dgvKPI.PointToClient(Cursor.Position);
			DataGridView.HitTestInfo hti = dgvKPI.HitTest(pt.X, pt.Y);
			if ( hti.Type == DataGridViewHitTestType.Cell ) {
				miEditKPI.Enabled = true;
				miRemoveKPI.Enabled = true;
				dgvKPI.ClearSelection();
				dgvKPI.Rows[hti.RowIndex].Selected = true;
			} else {
				miEditKPI.Enabled = false;
				miRemoveKPI.Enabled = false;
			}
		}

		private void miEditKPI_Click(object sender, EventArgs e)
		{
			editKPI();
		}
		private void miNewKPI_Click(object sender, EventArgs e)
		{
			newKPI();
		}
		private void miRemoveKPI_Click(object sender, EventArgs e)
		{
			removeKPI();
		}

		private void dgvKPI_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
		{
			if ( e.RowIndex > -1 ) {
				KPIMetric metric = dgvKPI.Rows[e.RowIndex].DataBoundItem as KPIMetric;
				if ( metric != null ) {
					KPI.FormKPIMetric frm = new OpenComposite.EII.KPI.FormKPIMetric(metric);
					frm.ShowDialog();
				}
				fillKPIList();
			}
		}

		private void btnSelInput_Click(object sender, EventArgs e)
		{
			Forms.FormSelectRepositoryEx frm = new OpenComposite.EII.Forms.FormSelectRepositoryEx(_verb);
			frm.AllowedTypes = new ItemType[] { ItemType.BObject };
			frm.DomainID = Global.Status.CurrentDomainId;
			frm.RepositoryID = Global.Status.CurrentRepositoryId;
			frm.MultiSelect = false;
			frm.SelectedItem = _verb.InputBusinessObject;
			if ( frm.ShowDialog() == DialogResult.OK ) {
				_verb.InputBusinessObject = frm.SelectedItem as BusinessObject;
				showInputOutput();
			}
		}

		private void btnSelOutput_Click(object sender, EventArgs e)
		{
			Forms.FormSelectRepositoryEx frm = new OpenComposite.EII.Forms.FormSelectRepositoryEx(_verb);
			frm.AllowedTypes = new ItemType[] { ItemType.BObject };
			frm.DomainID = Global.Status.CurrentDomainId;
			frm.RepositoryID = Global.Status.CurrentRepositoryId;
			frm.MultiSelect = false;
			frm.SelectedItem = _verb.OutputBusinessObject;
			if ( frm.ShowDialog() == DialogResult.OK ) {
				_verb.OutputBusinessObject = frm.SelectedItem as BusinessObject;
				showInputOutput();
			}
		}

		private void btnViewInput_Click(object sender, EventArgs e)
		{
			showSchema(_verb.InputBusinessObject);
		}
		private void btnRemoveInput_Click(object sender, EventArgs e)
		{
			_verb.InputBusinessObject = null;
			showInputOutput();
		}

		private void btnViewOutput_Click(object sender, EventArgs e)
		{
			showSchema(_verb.OutputBusinessObject);
		}
		private void btnRemoveOutput_Click(object sender, EventArgs e)
		{
			_verb.OutputBusinessObject = null;
			showInputOutput();
		}

		private void btnSelectLogMethod_Click(object sender, EventArgs e)
		{
			Forms.FormSelectLogicalMethod frm = new Forms.FormSelectLogicalMethod(_verb,
				_verb.InputBusinessObjectID, _verb.OutputBusinessObjectID);
			frm.RepositoryID = Global.Status.CurrentRepositoryId;
			frm.DomainID = Global.Status.CurrentDomainId;
			frm.MultiSelect = false;
			frm.SelectedItem = _verb.DefaultLogicalMethod;
			if ( frm.ShowDialog() == DialogResult.OK ) {
				//_verb.DefaultLogicalMethod = frm.SelectedItem as Repository.LogicalWebMethod;
				setDefaultLogMethod(frm.SelectedItem as Repository.LogicalWebMethod);
				displayLogMethod();
			}
		}
		private void btnCreateLogMethod_Click(object sender, EventArgs e)
		{
			RepositoryService rs = _verb.GetService(typeof(RepositoryService)) as RepositoryService;
			Debug.Assert(rs != null);

			Repository.IRepositoryItem parent = null;
			Repository.IRepositoryItem parentNew;
			Repository.LogicalWebMethod logwm =
				rs.GetNewItem<Repository.LogicalWebMethod>(false, ref parent);

			this.Refresh();
			if ( logwm == null ) return;

			int domainId = Global.Status.CurrentDomainId;
			int folderId = -1;
			if ( parent != null && parent.RepositoryItemType == OpenComposite.EII.Repository.ItemType.GenericFolder )
				folderId = parent.ID;
			if ( logwm.ShowNewItemFormEx(Global.Status.CurrentRepositoryId, false, parent,
					ref domainId, out parentNew,
					_verb.InputBusinessObject, _verb.OutputBusinessObject)
				 != DialogResult.OK ) {
				return;
			}
			if ( parentNew != null ) {
				Global.Data.AddRepositoryHierarchy(parentNew, logwm, Global.Status.CurrentRepositoryId);
			} else {
				Global.Data.AddRepositoryItemToDomainFolder(Global.Status.CurrentDomainId, logwm);
			}
			//_verb.DefaultLogicalMethod = logwm;
			setDefaultLogMethod(logwm);
			displayLogMethod();
		}
		private void btnRemoveLogMethod_Click(object sender, EventArgs e)
		{
			_verb.DefaultLogicalMethod = null;
			displayLogMethod();
		}

		private void txtBO_DragOver(object sender, DragEventArgs e)
		{
			if ( e.Data.GetDataPresent(typeof(BusinessObject)) ) {
				e.Effect = DragDropEffects.Link;
			} else {
				e.Effect = DragDropEffects.None;
			}
		}
		private void txtBO_DragDrop(object sender, DragEventArgs e)
		{
			if ( e.Data.GetDataPresent(typeof(BusinessObject)) ) {
				BusinessObject bo = (BusinessObject)e.Data.GetData(typeof(BusinessObject));
				if ( sender == txtInput ) {
					_verb.InputBusinessObject = bo;
				} else if ( sender == txtOutput ) {
					_verb.OutputBusinessObject = bo;
				}
				showInputOutput();
			}
		}

		private void txtLogMethod_DragOver(object sender, DragEventArgs e)
		{
			if ( e.Data.GetDataPresent(typeof(LogicalWebMethod)) ) {
				LogicalWebMethod lwm = (LogicalWebMethod)e.Data.GetData(typeof(LogicalWebMethod));
				if ( lwm.InputBusinessObjectID == _verb.InputBusinessObjectID &&
					 lwm.OutputBusinessObjectID == _verb.OutputBusinessObjectID ) {
					e.Effect = DragDropEffects.Link;
				} else {
					e.Effect = DragDropEffects.None;
				}
			} else {
				e.Effect = DragDropEffects.None;
			}
		}
		private void txtLogMethod_DragDrop(object sender, DragEventArgs e)
		{
			if ( e.Data.GetDataPresent(typeof(LogicalWebMethod)) ) {
				LogicalWebMethod lwm = (LogicalWebMethod)e.Data.GetData(typeof(LogicalWebMethod));
				if ( lwm.InputBusinessObjectID == _verb.InputBusinessObjectID &&
					 lwm.OutputBusinessObjectID == _verb.OutputBusinessObjectID ) {
					_verb.DefaultLogicalMethod = lwm;
					displayLogMethod();
				}
			}
		}

		private void tabCtrlMain_Selected(object sender, TabControlEventArgs e)
		{
			if ( e.TabPage == tabUsedBy ) {
				usedByHierarchyVerb.RepositoryItem = this.RepositoryItem as RepositoryItemBaseEx;
			} else if ( e.TabPage == tabUses ) {
				usingHierarchyVerb.RepositoryItem = this.RepositoryItem as RepositoryItemBaseEx;
			}
		}

		#endregion

		private void txtVerbName_KeyPress(object sender, KeyPressEventArgs e)
		{
			if ( e.KeyChar < (char)32 ) return;
			e.Handled = !Helpers.IsValidCharForName(e.KeyChar);
		}

		#endregion

		protected override void NotifyPropertyChange(string property, object value)
		{
			if ( property == "Name" && value != null ) {
				txtVerbName.Text = value.ToString();
			}
		}

		private void dgvKPI_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
		{
			if ( e.RowIndex < 0 ) return;
			if ( e.ColumnIndex == colKPIValue.Index ) {
				KPIMetric metric = dgvKPI.Rows[e.RowIndex].DataBoundItem as KPIMetric;
				if ( metric == null ) return;
				e.Value = Helpers.ConvertUnit(e.Value.ToString(), metric.Kpi.BaseUnit, metric.Kpi.GetKpiUnit(metric.Unit));
			}
		}
	}
}
